<template>
  <div>
    <n-card>
      <n-space style="margin-bottom: 10px">
        <n-input v-model:value="searchWord" placeholder="请输入标题" style="width: 300px">
        </n-input>
        <n-button type="primary" @click="getList">查询</n-button>
      </n-space>
    </n-card>
    <n-card style="margin-top: 5px">
      <n-space>
      <n-button type="primary" style="margin-bottom: 5px;"
                @click="mediaDownloadInfo = null ; downloadModal = !downloadModal">
        <template #icon>
          <n-icon>
            <AddCircleOutline/>
          </n-icon>
        </template>
        新增下载
      </n-button>

      <n-button type="info" style="margin-bottom: 5px " @click="uploadFile">
        <template #icon>
          <n-icon>
            <AttachSharp/>
          </n-icon>
        </template>
        上传文件
      </n-button>
        <n-tag type="primary" size="large" style=" margin-bottom: 5px " :bordered="false">如果上传文件点击无反应，请按F5刷新页面！！</n-tag>
        <n-tag type="error" size="large" strong v-if="!ffmpegOk" :bordered="false">FFmpeg环境变量未设置好,请先设置，重启系统</n-tag>
      </n-space>

      <n-data-table
          :columns="columns"
          :data="mediaInfoList"
          :loading="tableLoading"
          :style="{ height: `${clientHeight - (layoutHeaderHeight  + tabsHeight + 224)}px` }"
          flex-height
      >
      </n-data-table>
      <n-space justify="end" style="margin-top: 10px">
        <n-pagination
            :display-order="['quick-jumper', 'pages', 'size-picker']"
            :item-count="tableTotal"
            :page-size="paginationReactive.pageSize"
            :page-sizes="paginationReactive.pageSizes"
            show-quick-jumper
            show-size-picker
            :on-update:page-size="onPageSizeChange"
            :on-update:page="onPageChange"
        />
      </n-space>
    </n-card>
    <n-modal
        v-model:show="downloadModal"
        preset="card"
        style=" width:600px"
        title="多媒体文件下载"
        size="huge"
        :bordered="false"
    >
      <n-alert  type="info" :bordered="false" :show-icon="false">
        支持B站 抖音视频下载<br/>
        <n-text type="warning">如果无法下载，则默认为视频网站调整策略,请等待版本更新</n-text>
      </n-alert>
      <n-form ref="formRef" :model="mediaInfoForm" style="margin-top: 15px;">
        <n-form-item>
          <n-radio-group v-model:value="mediaInfoForm.type">
            <n-radio value="1">抖音</n-radio>
            <n-radio value="2">B站以及其他</n-radio>
          </n-radio-group>
        </n-form-item>

        <n-form-item
            label="视频地址"
            path="name"
        >
          <n-input v-model:value="mediaInfoForm.link" @change="selectType" clearable/>
          <n-button style="margin-left: 5px;" type="primary" @click="proxyDownload" :loading="proxyLoading">解析
          </n-button>
        </n-form-item>
        <div v-if="mediaDownloadInfo">
          <h4>{{ mediaDownloadInfo.title }}</h4>
          <n-space justify="end">
            <n-tag type="info" strong>{{ mediaDownloadInfo.type }}</n-tag>
            <n-tag type="success" strong style="margin-left: 5px">{{ mediaDownloadInfo.site }}</n-tag>
          </n-space>
          <n-list>
            <n-list-item style="padding: 0; margin-top: 10px" v-for="item in mediaDownloadInfo?.steamList">

              <n-thing v-if="item.parts != null && item.parts.length >0 " style="padding-left: 0;margin-bottom: 10px"
                       :title="item.quality" content-style="margin-top: 10px;">
                <n-thing v-for="part in item.parts">
                  <n-space>
                    <n-ellipsis style="max-width:500px">
                      {{ part.url }}
                    </n-ellipsis>
                  </n-space>
                  <n-space justify="space-between">
                    <n-space>
<!--                      <n-tag type="info">{{ part.size }}</n-tag>-->
                      <n-tag type="warning">{{ part.ext }}</n-tag>
                    </n-space>
                    <n-space>
                      <n-button size="small" type="primary" @click="submitDownloadTask(item,part)">下载</n-button>
                    </n-space>
                  </n-space>
                </n-thing>
              </n-thing>

              <template #suffix v-if="item.parts == null && item.parts.length == 0 ">
                <n-button type="primary" @click="submitDownloadTask(item)">下载</n-button>
              </template>
              <n-thing v-if="item.parts == null && item.parts.length ==0 " style="padding-left: 0;margin-bottom: 10px"
                       :title="item.quality" content-style="margin-top: 10px;">
                <n-tag type="info">{{ item.size }}</n-tag>
                <n-tag v-if="item.ext != null && item.ext!=''" type="warning">{{ item.ext }}</n-tag>
              </n-thing>
            </n-list-item>

          </n-list>
        </div>
      </n-form>
    </n-modal>

    <n-modal v-model:show="txtShow">
      <n-card
          style="width: 600px"
          title="文本内容"
          :bordered="false"
          size="huge"
          role="dialog"
          aria-modal="true"
      >
        <template #header-extra>
          <n-button type="info" @click="exportFile('srt')">导出SRT</n-button>
          <n-button  type="info" @click="exportFile('txt')" style="margin-left: 5px;">导出TXT</n-button>
        </template>
        <n-spin :show="txtLoading">
          <n-scrollbar style="max-height: 500px">
            <n-table>
              <thead>
              <tr>
                <th>开始</th>
                <th>结束</th>
                <th>文本内容</th>
              </tr>
              </thead>
              <tbody>
              <tr v-for="item in txtContents">
                <td>{{ item.startTime }}</td>
                <td>{{ item.endTime }}</td>
                <td>{{ item.videoText }}</td>
              </tr>
              </tbody>
            </n-table>
          </n-scrollbar>
        </n-spin>
      </n-card>
    </n-modal>
    <VideoBox ref="videoBoxRef"></VideoBox>
    <!--音频播放器-->
    <n-modal
        v-model:show="audioModelShow"
        preset="card"
        style="width: 600px"
        :title="audioOption.name"
        size="huge"
        :bordered="false"
        segmented="{
              content: 'soft',
              footer: 'soft'
          }"
    >
      <AudioPlayer
          :option="audioOption"
      />
    </n-modal>

    <n-modal
        v-model:show="videoToTextModalShow"
        :mask-closable="false"
        preset="card"
        :style="{
          width: '900px'
        }"
        title="OCR识别"
        size="huge"
        :bordered="false"
        :segmented="{
          content: true,
          footer: 'soft'
        }"
        @close="getList"
    >
      <n-space vertical>
        <n-steps :current="(ocrProgressCurrent as number)">
          <n-step
              title="视频截图"
          />
          <n-step
              title="OCR识别"
          />

          <n-button-group>
            <n-button @click="ocrProgressCurrent > 1 ? ocrProgressCurrent--:1">
              <template #icon>
                <n-icon>
                  <ArrowBackCircle />
                </n-icon>
              </template>
            </n-button>
            <n-button @click="ocrProgressCurrent < 2 ? ocrProgressCurrent++:2">
              <template #icon>
                <n-icon>
                  <ArrowForwardCircle/>
                </n-icon>
              </template>
            </n-button>
          </n-button-group>
        </n-steps>
      </n-space>

      <n-card v-if="ocrProgressCurrent === 1" :bordered="false">
        <n-h4 v-if="selectMedia.screenshotStatus != 'SUCCESS'">您一共需要生成{{ totalNum }}张参考图</n-h4>
        <n-progress
            v-if="selectMedia.screenshotStatus != 'SUCCESS'"
            type="line"
            :percentage=" finishNum === 0? 0 : Math.round(finishNum/totalNum *100) "
            :height="30"
            :border-radius="5"
            :fill-border-radius="0"
        >
        </n-progress>
        <n-progress
            v-else
            type="line"
            :percentage=" 100 "
            :height="30"
            :border-radius="5"
            :fill-border-radius="0"
        >
        </n-progress>
      </n-card>
      <n-card v-if="ocrProgressCurrent === 2" :bordered="false">
        <n-form>
          <n-form-item label="OCR模式">
            <n-select :options="ocrOption" v-model:value="ocrForm.ocrMode"
                      @update:value="handOcrModelSelect"></n-select>
          </n-form-item>
          <n-form-item label="区域信息" v-if="ocrForm.ocrMode=='2' ">
            <n-input v-model:value="ocrForm.ocrArea">
            </n-input>
          </n-form-item>
          <n-form-item label="进度">
            <n-progress
                type="line"
                :percentage="finishNumOcr === 0? 0 : Math.round(finishNumOcr/totalNumOcr *100) "
                :height="30"
                :border-radius="5"
                :fill-border-radius="0"
            />
          </n-form-item>
        </n-form>
      </n-card>
        <template #footer>
          <n-row>
            <n-col :span="12">
              <n-space  style="margin-top:30px">
                <n-tooltip trigger="hover">
                  <template #trigger>
                    <n-button type="primary" @click="ocrToText" :loading="ocrLoading">一键执行</n-button>
                  </template>
                  一键执行在OCR阶段会使用全图OCR,默认选择最底部文字
                </n-tooltip>

              </n-space>
            </n-col>
            <n-col :span="12">
              <n-space justify="end" style="margin-top:30px">
                <n-button v-if="ocrProgressCurrent==1"  type="primary" @click="batchScreenshot" :loading="ocrLoading">批量截图</n-button>
                <n-button v-if="ocrProgressCurrent==2" type="primary" @click="batchOCR" :loading="ocrLoading">批量识别</n-button>
              </n-space>
            </n-col>
          </n-row>
        </template>
      <n-modal
          v-model:show="ocrEditModalShow"
          class="custom-card"
          preset="card"
          :style="{
          width: '900px'
        }"
          title="选择识别区域"
          size="huge"
          :bordered="false"
      >
        <Ocredit :filePath="selectMedia.fileUserId" @loadArea-Event="loadAreaEvent"></Ocredit>
      </n-modal>
    </n-modal>


    <n-modal
        v-model:show="importSRTModalShow"
        class="custom-card"
        preset="card"
        :style="{
          width: '900px'
        }"
        title="输入SRT内容"
        size="huge"
        :bordered="false"
    >
      <n-form>
        <n-form-item :show-label=false>
          <n-input type="textarea" style="height: 500px;" v-model:value="srtContent">

          </n-input>
        </n-form-item>
      </n-form>
      <n-space justify="end" style="margin-top:10px">
        <n-button type="primary" @click="importSRT" :loading="ocrLoading">导入SRT</n-button>
      </n-space>
    </n-modal>

    <n-modal v-model:show="logModalShow" transform-origin="center">
      <n-card
        style="width: 1200px"
        title="转换日志"
        :bordered="false"
        size="huge"
        role="dialog"
        aria-modal="true"
      >
        <template>
          转换日志
        </template>
        <template #header-extra>
          <n-tag type="primary" style="margin-right: 5px">
            由于解析问题，显示汉字为?号，请勿在意
          </n-tag>
          <n-space>
            <n-button size="small" type="info" @click="logModalShow = false">关闭</n-button>
          </n-space>
        </template>
        <n-scrollbar style="max-height: 500px" trigger="none">
          <n-li v-for="log in logs">
            {{log}}
          </n-li>
        </n-scrollbar>
      </n-card>
    </n-modal>

    <n-drawer v-model:show="revisionShow" :width="drawerWidth" :close-on-esc="false" :mask-closable="false">
      <n-drawer-content title="文本修正" closable>
        <revisionWhisperText v-if="selectMedia?.fileUserId!=null" :closeAction="closeAction" :userFileId="selectMedia.fileUserId"></revisionWhisperText>
      </n-drawer-content>
    </n-drawer>

  </div>

</template>

<script lang="ts" setup>
import {h, onMounted, reactive, ref} from 'vue'
import {NButton, NPopselect, NTag, useNotification} from "naive-ui";
//@ts-ignore
import Bus from '@/components/file/box/GlobalUploader/utils/bus.js'
//@ts-ignore
import fileFunction from '@/libs/globalFunction/file.js'
import dayjs from 'dayjs'
import {mediaController} from '@/api/controller/media/mediaController'
import {whisperController} from "@/api/controller/media/whisperController"
import {sysParamController} from "@/api/controller/sysParamController"
import VideoBox from "@/components/file/box/videoPreview/BoxMask.vue"
import {AddCircleOutline, AttachSharp, Options,ArrowBackCircle,ArrowForwardCircle} from "@vicons/ionicons5"


const {
  clientHeight,
  layoutHeaderHeight,
  darkTheme,
  tabsHeight
} = storeToRefs(useSystemStore());

// import AudioPlayer from "vue3-audio-player";
import AudioPlayer from '@/components/file/audio/AudioPlayer.vue'
import defaultMusicPng from '@/assets/images/file/file_music.png'
import 'vue3-audio-player/dist/style.css'
import {videoController} from "@/api/controller/video/videoController.api";
import {ocrController} from "@/api/controller/media/ocrController";
import Ocredit from "@/components/ocr/ocredit.vue";
import {storeToRefs} from "pinia";
import {useSystemStore} from "@/store/modules/useSystemStore";
import revisionWhisperText from "@/components/gpt/revisionWhisperText/revisionWhisperText.vue";

const mediaInfoList = ref<Array<any>>([])
const searchWord = ref('')
const tableLoading = ref(false)
const downloadModal = ref(false)
const formRef = ref(null)
const proxyLoading = ref(false)
const mediaDownloadInfo = ref(null)
const notification = useNotification()
const txtShow = ref(false)
const txtContents = ref(null)
const txtLoading = ref(false)
const videoBoxRef = ref(null)
const mediaInfoForm = reactive({
  link: '',
  title: null,
  type: '1'
})
const audioModelShow = ref(false)
const logModalShow = ref(false)
const logs = ref([])
const systemParamModelShow = ref(false)
const audioOption = ref({
  src: '',
  title: '',
  coverImage: '',
  name: ''
})
const adapterOptions = ref([])
const selectAdapter = ref('')
const modelPath = ref('')
const bilibiliCookie = ref('')
const videoToTextModalShow = ref(false)
const ocrProgressCurrent = ref(1)
const totalNum = ref(0)
const finishNum = ref(0)
const totalNumOcr = ref(0)
const finishNumOcr = ref(0)
const importSRTModalShow = ref(false)
const srtContent = ref('')
const ocrOption = ref([{
  label: '全图OCR,默认选择最底部文字',
  value: '1'
}, {
  label: '自选区域',
  value: '2'
}])

const selectMedia = ref(null)
const ocrForm = reactive({
  ocrMode: '1',
  ocrArea: ''
})

const ocrEditModalShow = ref(false)
const ocrLoading = ref(false)
const revisionShow = ref(false)
const drawerWidth = ref(0)

const submitDownloadTask = (item: any, part?: any) => {
  const data = ref({
    link: mediaInfoForm.link,
    title: mediaDownloadInfo.value.title,
    ext: part.ext,
    quality: item.quality,
    size: item.size,
    site: mediaDownloadInfo.value.site,
    type: mediaDownloadInfo.value.type,
    code: item.code,
    name: item.name,
    quality: item.quality,
    downloadType: mediaInfoForm.type
  })
  if (mediaInfoForm.type==='1'){
    data.value.link = mediaDownloadInfo.value.steamList[0].parts[0].url
  }

  console.log(data)
  if (mediaDownloadInfo.value.site === '哔哩哔哩 bilibili.com') {
    data.cookie = bilibiliCookie.value
  }

  mediaController.submitDownloadTask(data.value).then((res) => {
    if (res.code === 200) {
      downloadModal.value = false
      notification['success']({
        content: '提示',
        meta: '下载任务已提交,请耐心等待',
        duration: 2500,
        keepAliveOnHover: true
      })
      getList()
    }
  })
}


const proxyDownload = () => {
  if (mediaInfoForm.link.length > 0) {
    proxyLoading.value = true
    const param = {
      link: mediaInfoForm.link
    }
    if (mediaInfoForm.link.startsWith('https://www.bilibili.com')) {
      param.cookie = bilibiliCookie.value
    }
    if (mediaInfoForm.type === '1') {
      mediaController.listDouyin(param).then(res => {
        if (res.code === 200) {
          mediaDownloadInfo.value = res.data
        }
      }).finally(() => {
        proxyLoading.value = false
      })
    } else {
      mediaController.listMediaInfo(param).then(res => {
        if (res.code === 200) {
          mediaDownloadInfo.value = res.data
        }
      }).finally(() => {
        proxyLoading.value = false
      })
    }

  }
}

const getList = () => {
  tableLoading.value = true
  const data = {}
  mediaController.listMediaList(data, {
    page: paginationReactive.page,
    pageSize: paginationReactive.pageSize
  }).then((res) => {
    tableLoading.value = false
    if (res.code === 200) {
      mediaInfoList.value = res.data.list
      tableTotal.value = res.data.count
      const key = ref(0)
      mediaInfoList.value.forEach((item) => {
        item.key = key.value
        key.value = key.value + 1
      })
    }
  }).catch((e: any) => {
    tableLoading.value = true
  })
}


const tableTotal = ref(0)
const deleteLoading = ref(false)

const deleteDownloadMedia = (row: any) => {
  window.$dialog.error({
    title: "温馨提醒",
    content: "删除操作不可逆，是否继续？",
    positiveText: "确定",
    negativeText: "取消",
    loading: deleteLoading.value,
    onPositiveClick: () => {
      deleteLoading.value = true
      mediaController.mediaDelete(row.id).then((res: any) => {
        deleteLoading.value = false
        if (res.code === 200) {
          window.$message.success(res.msg)
          getList()
        }
      })
    }
  })
}


const doVideoToTxt = (row: string) => {
  window.$dialog.info({
    title: "温馨提醒",
    content: "转文本是后台耗时操作，是否继续?",
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: () => {
      const data = {
        language: 'zh',
        modelPath: modelPath.value,
        gpu: selectAdapter.value,
        userFileId: row.fileUserId
      }
      whisperController.submitLocalWhisperTask(data).then((res) => {
        if (res.code === 200) {
          notification['success']({
            content: '提示',
            meta: '转文本任务已提交,请耐心等待',
            duration: 2500,
            keepAliveOnHover: true
          })
          getList()
        }
      })
    }
  })
}


const getText = (row: any) => {
  // 查看文本
  txtShow.value = true
  whisperController.getText(row.fileUserId).then((res) => {
    if (res.code === 200) {
      txtContents.value = res.data
    }
  })
}


const getAdapter = () => {
  whisperController.getAdapter().then((res) => {
    if (res.code === 200) {
      res.data.forEach((item: any) => {
        // @ts-ignore
        adapterOptions.value.push({
          label: item,
          value: item
        })
      })
    }
  })
}


const paginationReactive = reactive({
  page: 1,
  pageSize: 10,
  pageSizes: [10, 30, 60]
})


const onPageChange = (page: number) => {
  paginationReactive.page = page
  getList()
}
const onPageSizeChange = (pageSize: number) => {
  paginationReactive.pageSize = pageSize
  getList()

}

const mediaToTextOptions = ref(
    [
      {
        label: '语音转文字',
        value: 'mediaToText'
      },
      // {
      //   label: 'OCR识别文字',
      //   value: 'ocrToText'
      // },
      {
        label: '导入SRT',
        value: 'importSRT'
      }
    ])
onMounted(() => {
  getList()
  isFfmpegOk()
  drawerWidth.value = window.innerWidth * 0.8
  window.addEventListener('resize', handleResize)
})
const handleResize = () => {
  drawerWidth.value = window.innerWidth * 0.8
}
const columns = [
  {
    title: '文件操作',
    key: 'id',
    width: 150,
    render: (rowData) => {
      const buttons = [];
      if (rowData.status == '0') {
        buttons.push(h(
          NButton,
          {
            size: 'small',
            type: 'primary',
            onClick: () => {
              console.log(rowData.ext)
              if (rowData.ext === 'mp4') {
                const videoList = [{
                  fileName: rowData.name,
                  extendName: rowData.ext,
                  fileUrl: fileFunction.getViewFilePathByUserFileId(rowData.fileUserId),
                }]
                videoBoxRef.value.previewVideo(videoList, 0)
              } else if (rowData.ext === 'm4a' || rowData.ext === 'mp3' || rowData.ext ==='wav') {
                audioModelShow.value = true
                audioOption.value.name = rowData.name
                audioOption.value.coverImage = defaultMusicPng
                audioOption.value.src = fileFunction.getViewFilePathByUserFileId(rowData.fileUserId)
              }
            }
          },
          {default: () => '播放'}
        ))
      }
      buttons.push(
        h(
          NButton,
          {
            size: 'small',
            type: 'error',
            style: 'margin-left: 5px',
            onClick: () => {
              deleteDownloadMedia(rowData)
            }
          },
          {default: () => '删除'}
        )
      )
      return buttons
    }
  },{
    title: '文件类型',
    key: 'ext',
    width: 100
  } , {
    title: '标题',
    key: 'name',
    width: 300,
    ellipsis: {
      tooltip: true,
      lineClamp: 1
    }
  },
  {
    title: '状态',
    key: 'status',
    width: 100,
    render: (row) => {
      if (row.status == '0') {
        return h(NTag, {type: 'success'}, {default: () => '成功'})
      } else if (row.status == '1') {
        return h(NTag, {type: 'error'}, {default: () => '失败'})
      } else {
        return h(NTag, {type: 'warning'}, {default: () => '下载中'})
      }
    }
  } , {
    title: '时长',
    key: 'videoTime',
    width: 100,
    render: (row) => {
      if (row.videoTime != null) {
        return formatSeconds(row.videoTime / 1000 / 1000)
      }
    }
  },
  {
    title: '操作',
    key: 'address',
    width: 300,
    render(rowData: any) {
      const buttons = [];
      if (rowData.videoToTxtStatus != 'SUCCESS' && rowData.status == '0' && rowData.videoToTxtStatus!="IN_PROGRESS") {
        buttons.push(h(
            NPopselect, {
              options: mediaToTextOptions.value,
              trigger: 'click',
              onUpdateValue: (key: string) => {
                if (key === 'mediaToText') {
                  doVideoToTxt(rowData)
                } else if (key === 'ocrToText') {
                  totalNum.value = 0
                  finishNum.value = 0
                  videoToTextModalShow.value = true
                  selectMedia.value = rowData
                  ocrProgressCurrent.value = 1
                  if (rowData.screenshotStatus == 'SUCCESS') {
                    ocrProgressCurrent.value = 2
                  }
                }else {
                  // 导入srt
                  importSRTModalShow.value = true
                  selectMedia.value = rowData
                }
              },
            }, {
              default: () => {
                return h(
                    NButton,
                    {
                      size: 'small',
                      type: 'warning',
                      style: 'margin-left: 5px',
                    },
                    {default: () => '转文本'}
                )
              }
            }
        ))


      } else if (rowData.videoToTxtStatus == 'IN_PROGRESS') {
        buttons.push(h(
            NButton,
            {
              size: 'small',
              type: 'warning',
              style: 'margin-left: 5px',
              loading: true
            },
            {default: () => '转换中'}
        ))

        buttons.push(h(
          NButton,
          {
            size: 'small',
            type: 'error',
            style: 'margin-left: 5px',
            onClick: () => {
              killWhisperTask(rowData)
            }
          },
          {default: () => '终止'}
        ))
        buttons.push(h(
          NButton,
          {
            size: 'small',
            type: 'warning',
            style: 'margin-left: 5px',
            onClick: () => {
              getTransLog(rowData)
            }
          },
          {default: () => '查看'}
        ))


      } else if (rowData.videoToTxtStatus == 'SUCCESS' || rowData.ocrStatus == 'SUCCESS') {

        buttons.push(h(
            NButton,
            {
              size: 'small',
              type: 'primary',
              style: 'margin-left: 5px',
              onClick: () => {
                selectMedia.value = rowData
                revisionShow.value = true

              }
            },
            {default: () => '文本更正'}
        ))

        buttons.push(h(
            NButton,
            {
              size: 'small',
              type: 'success',
              style: 'margin-left: 5px',
              onClick: () => {
                selectMedia.value = rowData
                getText(rowData)

              }
            },
            {default: () => '查看文本'}
        ))

        buttons.push(h(
            NButton,
            {
              size: 'small',
              type: 'error',
              style: 'margin-left: 5px',
              onClick: () => {
                window.$dialog.error({
                  title: "温馨提醒",
                  content: "删除操作不可逆，是否继续？",
                  positiveText: "确定",
                  negativeText: "取消",
                  loading: deleteLoading.value,
                  onPositiveClick: () => {
                    deleteLoading.value = true
                    mediaController.deleteTextRecord(rowData.fileUserId).then(res=>{
                      if(res.code === 200){
                        window.$message.success(res.msg)
                      }
                    }).finally(()=>{
                      getList()
                      deleteLoading.value = false
                    })
                  }
                })
              }
            },
            {default: () => '删除文本'}
        ))


      } else if (rowData.videoToTxtStatus == 'FAILURE') {
        buttons.push(h(
            NButton,
            {
              size: 'small',
              type: 'warning',
              style: 'margin-left: 5px',
              onClick: () => {
                doVideoToTxt(rowData.fileUserId)
              }
            },
            {default: () => '转换失败,点击重试'}
        ))
      }
      return buttons
    }
  }
]


/**
 * 上传文件按钮点击事件
 * @description 通过Bus通信，开启全局上传文件流程
 * @param {boolean} uploadWay 上传方式 0-文件上传 1-文件夹上传 2-粘贴图片或拖拽上传
 */

const uploadFile = () => {
  // 获取当前日期格式
  const dateStr = dayjs(Date.now()).format('YYYYMMDD')
  const uploadFileParams = ref({
    filePath: '/下载/',
    isDir: 0,
    accept: 'image/*',
  })
  // 打开文件选择框
  Bus.emit('openUploader', {
    // 给服务端的额外参数
    params_: uploadFileParams,
    // 上传方式
    uploadWay_: '1',
    callType_: 1
  })
}

// 文件上传成功的回调
Bus.on('fileSuccess', (file: any) => {
  console.log('fuleSuccess',file)
  addMediaInfo(file)
})

/**
 * 任务类型成功之后的回调
 * taskType: 任务类型
 * sId: 关联主键ID
 */
Bus.on('actionSuccess', () => {
  getList()
})



const addMediaInfo = (file: any) => {
  const query = file.uploader.opts.query
  query.fileName = file.name
  query.md5 = file.uniqueIdentifier
  if (query.filePath.startsWith('/下载')) {
    // 新增media记录
    mediaController.addMediaInfo(query).then((res) => {
      if (res.code === 200) {
        notification['success']({
          content: '提示',
          meta: '上传成功',
          duration: 2500,
          keepAliveOnHover: true
        })
        getList()
      }
    })
  }
}

function formatSeconds(seconds) {
  const hour = Math.floor(seconds / 3600);
  seconds = seconds % 3600;
  const minute = Math.floor(seconds / 60);
  seconds = Math.floor(seconds % 60);

  return [
    hour.toString().padStart(2, '0'),
    minute.toString().padStart(2, '0'),
    seconds.toString().padStart(2, '0')
  ].join(':');
}


const ocrToText = async () => {
  totalNumOcr.value = 0 ;
  finishNumOcr.value = 0 ;
  totalNum.value = 0 ;
  finishNum.value = 0 ;
  if (selectMedia.value.screenShotStatus != 'SUCCESS') {
    try {
      await batchScreenshot()
    } catch (e) {
      console.log(e)
    }
    ocrProgressCurrent.value = ocrProgressCurrent.value + 1
  }
  await batchOCR()
}

const batchOCR = async () => {
  totalNumOcr.value = 0
  finishNumOcr.value = 0
  ocrLoading.value = true
  const param = {
    userFileId: selectMedia.value.fileUserId,
    type: ocrForm.ocrMode,
    area: ocrForm.ocrArea
  }
  await ocrController.ocrAndCheckLog(param, 10 * 60 * 1000, videoToTextModalShow, totalNumOcr, finishNumOcr).then(res => {
    totalNumOcr.value = res.taskLog.totalNum
    finishNumOcr.value = res.taskLog.finishNum
  }).finally(() => {
    ocrLoading.value = false
  })
}



const batchScreenshot = async () => {
  ocrLoading.value = true
  const param = {
    userFileId: selectMedia.value.fileUserId
  }
  await videoController.batchScreenshot(param).then(res => {
    console.log(res)
  }).finally(() => {
    ocrLoading.value = false
  })
}


const handOcrModelSelect =(value: string)=>{
  if(value === '2'){
    ocrForm.ocrArea = ''
    ocrEditModalShow.value = true
  }
}

const loadAreaEvent = (area: any) => {
  ocrForm.ocrArea = JSON.stringify(area)
  ocrEditModalShow.value = false
}

const exportFile = (type:string) => {
  if(type === "srt"){
    let srt = '';
    let index = 1;
    for (let i = 0; i < txtContents.value.length; i++) {
      let start = convert(txtContents.value[i].startTime);
      let end = convert(txtContents.value[i].endTime);
      let text = txtContents.value[i].videoText;
      srt += index + '\n';
      srt += start + ' --> ' + end + '\n';
      srt += text + '\n\n';
      index++;
    }
    downloadSrt(srt)
  }else {
    let txt = '';
    for (let i = 0; i < txtContents.value.length; i++) {
      let text = txtContents.value[i].videoText;
      txt += text + '\n';
    }
    downloadTxt(txt)
  }
}

function convert(secondsstr:number){
    const hours = Math.floor(secondsstr / 3600);
    const minutes = Math.floor((secondsstr % 3600) / 60);
    const seconds = Math.floor(secondsstr % 60);
    const milliseconds = (secondsstr.toString().split('.')[1] || '000').padEnd(3, '0');
    // Format as two-digit strings
    const hoursStr = String(hours).padStart(2, '0');
    const minutesStr = String(minutes).padStart(2, '0');
    const secondsStr = String(seconds).padStart(2, '0');
    const millisecondsStr = String(milliseconds).padStart(3, '0');
    // SRT time format: hh:mm:ss,mmm
    return `${hoursStr}:${minutesStr}:${secondsStr},${millisecondsStr}`
}

function downloadSrt(srt:string) {
  let element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(srt));
  element.setAttribute('download', selectMedia.value.name + '.srt');
  element.style.display = 'none';
  document.body.appendChild(element);
  element.click();
  document.body.removeChild(element);
}


function downloadTxt(srt:string) {
  let element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(srt));
  element.setAttribute('download', selectMedia.value.name + '.txt');
  element.style.display = 'none';
  document.body.appendChild(element);
  element.click();
  document.body.removeChild(element);
}


const importSRT = ()=>{
  if( srtContent.value ===''){
    window.$message.warning('请输入SRT内容')
  }
  const srtData = extractSubtitles(srtContent.value)
  if( srtData != null && srtData.length > 0){
    const param = {
      mediaId: selectMedia.value.id,
      videoTextList: srtData
    }
    ocrLoading.value = true
      mediaController.importSRT(param).then(res=>{
        if(res.code === 200){
          window.$message.success(res.msg)
          importSRTModalShow.value = false
          getList()
        }
      }).finally(()=>{
        ocrLoading.value = false
      })
  }
}


// 从 SRT 文件中提取字幕
function extractSubtitles(srt) {
  const subtitles = [];
  const lines = srt.trim().split('\n');
  let index = 0;
  while (index < lines.length) {
    if( lines[index] === ''){
      index++;
      continue;
    }
    const id = parseInt(lines[index++]);
    const time = lines[index++];
    const [startTime, endTime] = time.split(' --> ').map(parseTime);
    const text = [];

    while (index < lines.length && lines[index]) {
      text.push(lines[index++]);
    }
    subtitles.push({ id, startTime, endTime, videoText: text.join('\n') });
    index++;
  }
  return subtitles;
}

// 将时间字符串转换为秒数
function parseTime(time) {
  const [hours, minutes, seconds] = time.split(':');

  if(seconds === 0){
    return hours * 3600 + minutes * 60;
  }else {
    const [secondsPart, milliseconds] = seconds.split(',').map(parseFloat);
    return hours * 3600 + minutes * 60 + secondsPart + milliseconds / 1000;
  }

  function isValidSrtLine(line) {
    const regex = /^(\d+)\n(\d{2}:\d{2}:\d{2},\d{3}) --> (\d{2}:\d{2}:\d{2},\d{3})\n(.+)\n$/;
    return regex.test(line);
  }

}

const getTransLog = (rowData:any) =>{
  logModalShow.value = true
  mediaController.getLog(rowData.videoToTextTaskId).then((res)=>{
    if(res.code === 200){
      logs.value = res.data
    }
  })
}

const killWhisperTask = (rowData:any)=>{
  window.$dialog.info({
    title: "温馨提醒",
    content: "终止操作不可逆，是否继续？",
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: () => {
      mediaController.killWhisperTask(rowData.videoToTextTaskId).then((res)=>{
        if(res.code === 200){
          window.$message.success(res.msg)
          getList()
        }
      })
    }
  })
}

const ffmpegOk = ref(false)
const isFfmpegOk = ()=>{
  mediaController.isFfmpegOk().then((res)=>{
    if(res.code === 200){
      if(res.data){
        ffmpegOk.value = true
      }else {
        ffmpegOk.value = false
      }
    }
  })
}

const closeAction=()=>{
  revisionShow.value = false
  getList()
}

const selectType=()=>{
  if (mediaInfoForm.link.length>0){
    if (mediaInfoForm.link.indexOf('douyin') > 0){
      mediaInfoForm.type = '1'
    }else {
      mediaInfoForm.type = '2'
    }
  }
}
</script>
